package com.lowca.news.entity;

import java.io.Serializable;
import java.util.Date;
import java.util.HashSet;
import java.util.Set;

import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;

import org.hibernate.annotations.Cache;
import org.hibernate.annotations.CacheConcurrencyStrategy;

@Entity
@Table(name = "t_user", catalog = "com_lowca_news")
@org.hibernate.annotations.Entity(dynamicInsert = true, dynamicUpdate = true)
@Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
public class User extends IdEntity implements Serializable {

	private static final long serialVersionUID = 1L;

	private String username;// 用户名
	private String password;// 密码
	private String email;// E-mail
	private Integer loginCount = 0;// 登录成功次数
	private Boolean enabled = Boolean.TRUE;// 账号是否启用
	private Boolean locked = Boolean.FALSE;// 账号是否锁定
	private Boolean expired = Boolean.FALSE;// 账号是否过期
	private Boolean credentialsExpired = Boolean.FALSE;// 凭证是否过期
	private Date lastLoginTime = new Date();// 最后登录时间
	private String registerIp;// 注册ip
	private String lastLoginIp;// 最后登录ip
	private Date registerTime = new Date();// 注册时间
	private Set<Role> roles = new HashSet<Role>(0); // 我拥有的角色
	private Set<Article> uploadArticles = new HashSet<Article>(0);// 我发表的文章
	private Set<Article> checkArticles = new HashSet<Article>(0);// 我审核的文章
	private Set<ArticleComment> articleComments = new HashSet<ArticleComment>(0);// 我发表的文章评论

	public User() {
		super();
	}

	public User(String username, String password, String email,
			Integer loginCount, Boolean enabled, Boolean locked,
			Boolean expired, Boolean credentialsExpired, Date lastLoginTime,
			String registerIp, String lastLoginIp, Date registerTime,
			Set<Role> Roles, Set<Role> roles, Set<Article> uploadArticles,
			Set<Article> checkArticles, Set<ArticleComment> articleComments) {
		super();
		this.username = username;
		this.password = password;
		this.email = email;
		this.loginCount = loginCount;
		this.enabled = enabled;
		this.locked = locked;
		this.expired = expired;
		this.credentialsExpired = credentialsExpired;
		this.registerIp = registerIp;
		this.lastLoginTime = lastLoginTime;
		this.lastLoginIp = lastLoginIp;
		this.registerTime = registerTime;
		this.roles = roles;
		this.uploadArticles = uploadArticles;
		this.checkArticles = checkArticles;
		this.articleComments = articleComments;
	}

	@Column(name = "username", length = 30, updatable = false, nullable = false, unique = true)
	public String getUsername() {
		return username;
	}

	public void setUsername(String username) {
		this.username = username;
	}

	@Column(name = "password", length = 64)
	public String getPassword() {
		return password;
	}

	public void setPassword(String password) {
		this.password = password;
	}

	@Column(name = "email", length = 100, unique = true, nullable = false)
	public String getEmail() {
		return email;
	}

	public void setEmail(String email) {
		this.email = email;
	}

	@Column(name = "login_count", length = 4)
	public Integer getLoginCount() {
		return loginCount;
	}

	public void setLoginCount(Integer loginCount) {
		this.loginCount = loginCount;
	}

	@Column(name = "enabled")
	public Boolean getEnabled() {
		return enabled;
	}

	public void setEnabled(Boolean enabled) {
		this.enabled = enabled;
	}

	@Column(name = "locked")
	public Boolean getLocked() {
		return locked;
	}

	public void setLocked(Boolean locked) {
		this.locked = locked;
	}

	@Column(name = "expired")
	public Boolean getExpired() {
		return expired;
	}

	public void setExpired(Boolean expired) {
		this.expired = expired;
	}

	@Column(name = "credentials_expired")
	public Boolean getCredentialsExpired() {
		return credentialsExpired;
	}

	public void setCredentialsExpired(Boolean credentialsExpired) {
		this.credentialsExpired = credentialsExpired;
	}

	@Column(name = "last_login_time")
	@Temporal(TemporalType.TIMESTAMP)
	public Date getLastLoginTime() {
		return lastLoginTime;
	}

	public void setLastLoginTime(Date lastLoginTime) {
		this.lastLoginTime = lastLoginTime;
	}

	@Column(name = "last_login_ip", length = 40)
	public String getLastLoginIp() {
		return lastLoginIp;
	}

	public void setLastLoginIp(String lastLoginIp) {
		this.lastLoginIp = lastLoginIp;
	}

	@Column(name = "register_ip", length = 40)
	public String getRegisterIp() {
		return registerIp;
	}

	public void setRegisterIp(String registerIp) {
		this.registerIp = registerIp;
	}

	@Column(name = "register_time", updatable = false)
	@Temporal(TemporalType.TIMESTAMP)
	public Date getRegisterTime() {
		return registerTime;
	}

	public void setRegisterTime(Date registerTime) {
		this.registerTime = registerTime;
	}

	@ManyToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY)
	@JoinTable(name = "t_user_has_role", catalog = "com_lowca_news", joinColumns = { @JoinColumn(name = "user_id", nullable = false, updatable = false) }, inverseJoinColumns = { @JoinColumn(name = "role_id", nullable = false, updatable = false) })
	public Set<Role> getRoles() {
		return roles;
	}

	public void setRoles(Set<Role> roles) {
		this.roles = roles;
	}

	@OneToMany(cascade = { CascadeType.ALL }, fetch = FetchType.LAZY, mappedBy = "uploader")
	public Set<Article> getUploadArticles() {
		return uploadArticles;
	}

	public void setUploadArticles(Set<Article> uploadArticles) {
		this.uploadArticles = uploadArticles;
	}

	@OneToMany(cascade = { CascadeType.ALL }, fetch = FetchType.LAZY, mappedBy = "checker")
	public Set<Article> getCheckArticles() {
		return checkArticles;
	}

	public void setCheckArticles(Set<Article> checkArticles) {
		this.checkArticles = checkArticles;
	}

	@OneToMany(cascade = { CascadeType.ALL }, fetch = FetchType.LAZY, targetEntity = ArticleComment.class, mappedBy = "publisher")
	public Set<ArticleComment> getArticleComments() {
		return articleComments;
	}

	public void setArticleComments(Set<ArticleComment> articleComments) {
		this.articleComments = articleComments;
	}

	public boolean equals(Object other) {
		if (this == other)
			return true;
		if (!(other instanceof User))
			return false;
		final User user = (User) other;
		if (!user.getUsername().equals(getUsername()))
			return false;
		return true;
	}

	public int hashCode() {
		int result;
		result = getUsername().hashCode();
		return result;
	}

}
